Skip to content

feat: add edit-wiki-page safe output#58

Draft
Copilot wants to merge 3 commits intomainfrom
copilot/add-edit-wiki-page-safeoutput
Draft

feat: add edit-wiki-page safe output#58
Copilot wants to merge 3 commits intomainfrom
copilot/add-edit-wiki-page-safeoutput

Conversation

Copy link
Contributor

Copilot AI commented Mar 19, 2026

Adds edit-wiki-page as a new safe output, enabling agents to create or update Azure DevOps wiki pages through the standard two-stage safe output pipeline.

Agent parameters

  • path — wiki page path (e.g. /Overview/Architecture); must not contain ..
  • content — markdown content (≥10 chars)
  • comment — optional commit message

Front-matter configuration

safe-outputs:
  edit-wiki-page:
    wiki-name: "MyProject.wiki"          # required
    wiki-project: "OtherProject"         # optional; defaults to pipeline project
    path-prefix: "/agent-output"         # restrict writes to this subtree
    title-prefix: "[Agent] "             # prepended to the last path segment
    comment: "Updated by agent"          # default commit message
    create-if-missing: true              # allow page creation (default: true)

Implementation

  • Stage 1 (MCP): validates path (no .., non-empty) and content length; strips control chars from path; applies full sanitize_text() to content and comment before writing to safe_outputs.ndjson
  • Stage 2 (executor): GET page to check existence and retrieve ETag → enforce path-prefix → apply title-prefix → PUT to ADO Wiki REST API 7.0 with If-Match for optimistic concurrency
  • Compiler: edit-wiki-page added to WRITE_REQUIRING_SAFE_OUTPUTS — compilation fails without a permissions.write service connection
  • Security: path-prefix restriction prevents writes outside authorized subtrees; belt-and-suspenders .. check in both Stage 1 and Stage 2

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • api.github.com (HTTP Only)
    • Triggering command: /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw proxy --allow api.github.com -z relro 282f9.04ys10cas81d8l5zktauyxl6k.12os18v.rcgu.o 282f9.0f7osk7u4kohtd36hmj1ckb8i.12os18v.rcgu.o 282f9.0o5rfzu380rlxqqbz17syrsqf.12os18v.rcgu.o 282f9.0yxhou4h03rc34xfgwb3ycjol.12os18v.rcgu.o 282f9.1kguf4195hs9940mk1dm0ggzz.12os18v.rcgu.o 282f9.1mpyvdv7pyxf3ng8yipyk525t.12os18v.rcgu.o 282f9.1nhqb1ozrjlvfoy7fjlhcb73n.12os18v.rcgu.o 282f9.1vv2t69d0488go0yafes2x70i.12os18v.rcgu.o 282f9.1y9ifn86zes848os8kg1vriyy.12os18v.rcgu.o 282f9.35ht4wuid56kfcqz3us8mrudk.12os18v.rcgu.o 282f9.37d5q5eh66ez0d8t579jzdj7r.12os18v.rcgu.o 282f9.3chzns1ewigd37fx2u2u3i0yy.12os18v.rcgu.o 282f9.3gooohxjhqsvqsv72zcoin4pf.12os18v.rcgu.o 282f9.3gysfdn2shg5iuu7drfrw41jg.12os18v.rcgu.o (packet block)
    • Triggering command: /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw proxy --allow api.github.com g/de�� lib/rustlib/x86_--error-format=json lib/rustlib/x86_--json=diagnostic-rendered-ansi,artifacts,future-incompat mbols.o -3723d82190d9318/home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw -3723d82190d9318compile -3723d82190d9318/home/REDACTED/work/ado-aw/ado-aw/tests/fixtures/minimal-agent.md -3723d82190d9318-o -372�� -3723d82190d9318-C -3723d82190d9318debuginfo=2 -3723d82190d9318--check-cfg -3723d82190d9318bash -3723d82190d9318--norc -3723d82190d9318--noprofile -3723d82190d9318-C (packet block)
    • Triggering command: /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw proxy --allow api.github.com 4.2h�� 4.2n53465ez0tip3gmgghhqx15y.18oqtqx.rcgu.o 4.2rmm7e11at3uonx71pkfb3yl3.18oqtqx.rcgu.o mbols.o ddf4723054b4c8.rbash ddf4723054b4c8.r--norc ddf4723054b4c8.r--noprofile ddf4723054b4c8.rmcp_macros.3372feaf42b34d35-cgu.3.rcgu.o ddf4�� mbols.o -980ba44bd5631a04.0e9n4tn2jsjz770vkg9u9zkj3.18oqtqx.rcgu.o -980ba44bd5631a04.0fo4o8mez4ycvnf3o20q2znp3.18oqtqx.rcgu.o -980ba44bd5631a0bash -980ba44bd5631a0--norc -980ba44bd5631a0--noprofile -980ba44bd5631a04.180vyceco4m9eb5c6ddlkj9i2.18oqtqx.rcgu.o (packet block)
  • dev.azure.com
    • Triggering command: /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw proxy --allow api.github.com --allow dev.azure.com --allow *.visualstudio.com 282f9.0o5rfzu380rlxqqbz17syrsqf.12os18v.rcgu.o 282f9.0yxhou4h03rc34xfgwb3ycjol.12os18v.rcgu.o 282f9.1kguf4195hs9940mk1dm0ggzz.12os18v.rcgu.o 282f9.1mpyvdv7pyxf3ng8yipyk525t.12os18v.rcgu.o 282f9.1nhqb1ozrjlvfoy7fjlhcb73n.12os18v.rcgu.o 282f9.1vv2t69d0488go0yafes2x70i.12os18v.rcgu.o 282f9.1y9ifn86zes848os8kg1vriyy.12os18v.rcgu.o 282f9.35ht4wuid56kfcqz3us8mrudk.12os18v.rcgu.o 282f9.37d5q5eh66ez0d8t579jzdj7r.12os18v.rcgu.o 282f9.3chzns1ewigd37fx2u2u3i0yy.12os18v.rcgu.o 282f9.3gooohxjhqsvqsv72zcoin4pf.12os18v.rcgu.o 282f9.3gysfdn2shg5iuu7drfrw41jg.12os18v.rcgu.o (dns block)
    • Triggering command: /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw proxy --allow api.github.com --allow dev.azure.com --allow *.visualstudio.com lib/rustlib/x86_/home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw lib/rustlib/x86_compile lib/rustlib/x86_/home/REDACTED/work/ado-aw/ado-aw/tests/fixtures/pipeline-trigger-agent.md lib/rustlib/x86_-o lib/�� lib/rustlib/x86_-C lib/rustlib/x86_debuginfo=2 known-linux-gnu/--check-cfg known-linux-gnu/bash build.c70f956276--norc eof6poe84onc.rcg--noprofile mpl-3723d82190d9-C (dns block)
    • Triggering command: /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw proxy --allow api.github.com --allow dev.azure.com --allow *.visualstudio.com ddf4723054b4c8.rbash ddf4723054b4c8.r--norc ddf4723054b4c8.r--noprofile ddf4723054b4c8.rmcp_macros.3372feaf42b34d35-cgu.3.rcgu.o ddf4�� mbols.o -980ba44bd5631a04.0e9n4tn2jsjz770vkg9u9zkj3.18oqtqx.rcgu.o bin/cargo -980ba44bd5631a0bash -980ba44bd5631a0--norc -980ba44bd5631a0--noprofile bin/cargo (dns block)
  • msazuresphere.visualstudio.com
    • Triggering command: /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw proxy --allow api.github.com --allow dev.azure.com --allow *.visualstudio.com 282f9.0o5rfzu380rlxqqbz17syrsqf.12os18v.rcgu.o 282f9.0yxhou4h03rc34xfgwb3ycjol.12os18v.rcgu.o 282f9.1kguf4195hs9940mk1dm0ggzz.12os18v.rcgu.o 282f9.1mpyvdv7pyxf3ng8yipyk525t.12os18v.rcgu.o 282f9.1nhqb1ozrjlvfoy7fjlhcb73n.12os18v.rcgu.o 282f9.1vv2t69d0488go0yafes2x70i.12os18v.rcgu.o 282f9.1y9ifn86zes848os8kg1vriyy.12os18v.rcgu.o 282f9.35ht4wuid56kfcqz3us8mrudk.12os18v.rcgu.o 282f9.37d5q5eh66ez0d8t579jzdj7r.12os18v.rcgu.o 282f9.3chzns1ewigd37fx2u2u3i0yy.12os18v.rcgu.o 282f9.3gooohxjhqsvqsv72zcoin4pf.12os18v.rcgu.o 282f9.3gysfdn2shg5iuu7drfrw41jg.12os18v.rcgu.o (dns block)
    • Triggering command: /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw proxy --allow api.github.com --allow dev.azure.com --allow *.visualstudio.com lib/rustlib/x86_/home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw lib/rustlib/x86_compile lib/rustlib/x86_/home/REDACTED/work/ado-aw/ado-aw/tests/fixtures/pipeline-trigger-agent.md lib/rustlib/x86_-o lib/�� lib/rustlib/x86_-C lib/rustlib/x86_debuginfo=2 known-linux-gnu/--check-cfg known-linux-gnu/bash build.c70f956276--norc eof6poe84onc.rcg--noprofile mpl-3723d82190d9-C (dns block)
    • Triggering command: /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw proxy --allow api.github.com --allow dev.azure.com --allow *.visualstudio.com ddf4723054b4c8.rbash ddf4723054b4c8.r--norc ddf4723054b4c8.r--noprofile ddf4723054b4c8.rmcp_macros.3372feaf42b34d35-cgu.3.rcgu.o ddf4�� mbols.o -980ba44bd5631a04.0e9n4tn2jsjz770vkg9u9zkj3.18oqtqx.rcgu.o bin/cargo -980ba44bd5631a0bash -980ba44bd5631a0--norc -980ba44bd5631a0--noprofile bin/cargo (dns block)
  • raw.github.com
    • Triggering command: /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw proxy --allow *.github.com /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/async_trait-0d9946b44b5e2a43.a/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/proxy_tests-bdf3f3fa375db968.277xkoqd5bwrczxu1godtun7e.09h86zq.rcgu.o /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/async_trait-0d9946b44b5e2a43.a/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/proxy_tests-bdf3f3fa375db968.2ggbp88eaerqa2hprceyhcpyc.09h86zq.rcgu.o 282f9.04ys10cas81d8l5zktauyxl6k.12os18v.rcgu.o 282f9.0f7osk7u4kohtd36hmj1ckb8i.12os18v.rcgu.o 282f9.0o5rfzu380rlxqqbz17syrsqf.12os18v.rcgu.o 282f9.0yxhou4h03rc34xfgwb3ycjol.12os18v.rcgu.o 282f9.1kguf4195hs9940mk1dm0ggzz.12os18v.rcgu.o 282f9.1mpyvdv7pyxf3ng8yipyk525t.12os18v.rcgu.o 282f9.1nhqb1ozrjlvfoy7fjlhcb73n.12os18v.rcgu.o 282f9.1vv2t69d0488go0yafes2x70i.12os18v.rcgu.o 282f9.1y9ifn86zes848os8kg1vriyy.12os18v.rcgu.o 282f9.35ht4wuid56kfcqz3us8mrudk.12os18v.rcgu.o 282f9.37d5q5eh66ez0d8t579jzdj7r.12os18v.rcgu.o 282f9.3chzns1ewigd37fx2u2u3i0yy.12os18v.rcgu.o 282f9.3gooohxjhqsvqsv72zcoin4pf.12os18v.rcgu.o 282f9.3gysfdn2shg5iuu7drfrw41jg.12os18v.rcgu.o (dns block)
    • Triggering command: /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw proxy --allow *.github.com g/de�� lib/rustlib/x86_--error-format=json lib/rustlib/x86_--json=diagnostic-rendered-ansi,artifacts,future-incompat mbols.o -3723d82190d9318/home/REDACTED/.rustup/toolchains/stable-x86_64-REDACTED-linux-gnu/-o -3723d82190d9318-flavor -3723d82190d9318gnu -3723d82190d9318-plugin -372�� -3723d82190d9318-plugin-opt=/usr/libexec/gcc/x86_64-linux-gnu/13/lto-wrapper -3723d82190d9318-plugin-opt=-fresolution=/tmp/cck1yKtD.res -3723d82190d9318--build-id -3723d82190d9318/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/compiler_tests-980ba44bd5631a0-plugin-opt=/usr/libexec/gcc/x86_64-linux-gnu/13/lto-wrapper -3723d82190d9318execute::tests -3723d82190d9318elf_x86_64 -3723d82190d9318--hash-style=gnu (dns block)
    • Triggering command: /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw proxy --allow *.github.com 4.2h�� 4.2n53465ez0tip3gmgghhqx15y.18oqtqx.rcgu.o 4.2rmm7e11at3uonx71pkfb3yl3.18oqtqx.rcgu.o mbols.o ddf4723054b4c8.rbash ddf4723054b4c8.r--norc ddf4723054b4c8.r--noprofile ddf4723054b4c8.r--hash-style=gnu ddf4�� mbols.o -980ba44bd5631a04.0e9n4tn2jsjz770vkg9u9zkj3.18oqtqx.rcgu.o -980ba44bd5631a04.0fo4o8mez4ycvnf3o20q2znp3.18oqtqx.rcgu.o -980ba44bd5631a0bash -980ba44bd5631a0--norc -980ba44bd5631a0--noprofile -980ba44bd5631a04.180vyceco4m9eb5c6ddlkj9i2.18oqtqx.rcgu.o (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

Let's draft an edit-wiki-page safeoutput for ado-aw.

Look at how other safe outputs are implemented in the code base.

The frontmatter should allow the user to configure the wiki name, path where files can be written, prepended text for each page title added, anything else that would be good to include based on the capabilities of the azure devops api.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Implements a new `edit-wiki-page` safe output that allows agents to
create or update Azure DevOps wiki pages.

Stage 1 (MCP server):
- `edit-wiki-page` tool registered on the SafeOutputs MCP server
- Validates path (no `..`, non-empty), content (≥10 chars)
- Strips control characters from path; full sanitize_text() on content/comment
- Queues result to safe_outputs.ndjson

Stage 2 (executor):
- Dispatches `edit-wiki-page` to EditWikiPageResult::execute_sanitized()
- GET wiki page to check existence and obtain ETag
- PUT to create/update with If-Match header for optimistic concurrency
- Enforces path-prefix restriction configured in front matter
- Applies title-prefix to final path segment if configured

Front-matter configuration (safe-outputs.edit-wiki-page):
- wiki-name: wiki identifier (required)
- wiki-project: ADO project override (optional)
- path-prefix: restrict writes to pages under this path (optional)
- title-prefix: prepend text to each page title (optional)
- comment: default commit message (optional)
- create-if-missing: allow creating new pages (default: true)

Compiler:
- edit-wiki-page added to WRITE_REQUIRING_SAFE_OUTPUTS so compilation
  fails if no permissions.write service connection is configured

Co-authored-by: jamesadevine <4742697+jamesadevine@users.noreply.github.com>
Copilot AI changed the title [WIP] Add edit wiki page safeoutput for ado-aw feat: add edit-wiki-page safe output Mar 19, 2026
Copilot AI requested a review from jamesadevine March 19, 2026 11:39
@jamesadevine
Copy link
Collaborator

@copilot implement the executor step too. Align with other executor implementations that use the devops api

Copy link
Contributor Author

Copilot AI commented Mar 19, 2026

@copilot implement the executor step too. Align with other executor implementations that use the devops api

The Stage 2 executor is already implemented in commit 4ccf0b2 inside src/tools/edit_wiki_page.rs (execute_impl on EditWikiPageResult). It follows the same ADO API patterns as create_work_item.rs and create_pr.rs:

  • Uses reqwest::Client::new() + basic_auth("", Some(token))
  • URL format {org_url.trim_end_matches('/')}/{project}/_apis/wiki/wikis/{wiki_name}/pages (same as create_work_item.rs)
  • GET the page first to check existence and capture the ETag from the response header
  • PUT with If-Match: {ETag} for optimistic concurrency on updates; no If-Match when creating a new page
  • Returns ExecutionResult::success_with_data with page id, url, wiki, project, and action (created/updated)
  • Returns ExecutionResult::failure with the HTTP status and error body on any API error

@jamesadevine
Copy link
Collaborator

/rust-review

@github-actions
Copy link
Contributor

github-actions bot commented Mar 19, 2026

Rust PR Reviewer completed successfully!

@github-actions
Copy link
Contributor

🔍 Rust PR Review

Summary: Looks good overall — solid new safe-output tool with good test coverage, but has two correctness issues worth addressing.

Findings

🐛 Bugs / Logic Issues

  • src/tools/edit_wiki_page.rs:35-39.. check is a substring match, not a path-component check

    ensure!(!self.path.contains(".."), "path must not contain '..'");

    This rejects legitimate wiki paths like /Release-Notes/v1.0..1 or /Topic/Foo..Bar. The check should be component-aware:

    ensure!(
        !self.path.split('/').any(|seg| seg == ".."),
        "path must not contain '..' as a path component"
    );

    The same substring check exists in execute_impl at line ~212 as a belt-and-suspenders guard — both should be updated.

  • src/tools/edit_wiki_page.rs:239-244wiki_name (and project) are interpolated raw into the URL path

    let base_url = format!(
        "{}/{}/_apis/wiki/wikis/{}/pages",
        org_url.trim_end_matches('/'),
        project,
        wiki_name,  // <-- no encoding
    );

    If wiki_name contains # (fragment delimiter) or ? (query start), reqwest will parse those characters structurally rather than encoding them, silently corrupting the URL. Spaces are handled (the url crate encodes them), but #/? are not. Since wiki_name comes from operator-controlled front matter this is low severity, but a percent_encoding::utf8_percent_encode(wiki_name, percent_encoding::NON_ALPHANUMERIC) (or the more permissive PATH_SEGMENT) encode would harden it. Note: project has the same pattern and this matches the existing style in create_work_item.rs, so fixing both consistently would be ideal.

✅ What Looks Good

  • Defense-in-depth sanitization model is solid: Stage 1 (MCP handler) manually sanitizes EditWikiPageParams before try_into(), and Stage 2 re-runs sanitize_fields() via execute_sanitized() — this is intentional and correct.
  • path_prefix enforcement in execute_impl is well-designed: it normalizes both the path and the prefix before comparison, and the test_execute_path_outside_prefix_rejected unit test covers the security boundary.
  • write_safe_output_file error is silently discarded (let _ = ...) — consistent with every other tool in mcp.rs; acceptable.
  • ETag-based optimistic concurrency for the PUT is a nice touch and prevents silent data races on concurrent runs.
  • Test coverage is thorough: validation, serialization, path helpers, sanitization, and executor failure modes are all exercised.

Generated by Rust PR Reviewer for issue #58 ·

@jamesadevine
Copy link
Collaborator

@copilot src/tools/edit_wiki_page.rs:239-244 — wiki_name (and project) are interpolated raw into the URL path

let base_url = format!(
"{}/{}/_apis/wiki/wikis/{}/pages",
org_url.trim_end_matches('/'),
project,
wiki_name, // <-- no encoding
);
If wiki_name contains # (fragment delimiter) or ? (query start), reqwest will parse those characters structurally rather than encoding them, silently corrupting the URL. Spaces are handled (the url crate encodes them), but #/? are not. Since wiki_name comes from operator-controlled front matter this is low severity, but a percent_encoding::utf8_percent_encode(wiki_name, percent_encoding::NON_ALPHANUMERIC) (or the more permissive PATH_SEGMENT) encode would harden it. Note: project has the same pattern and this matches the existing style in create_work_item.rs, so fixing both consistently would be ideal.

Co-authored-by: jamesadevine <4742697+jamesadevine@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 19, 2026

@copilot src/tools/edit_wiki_page.rs:239-244 — wiki_name (and project) are interpolated raw into the URL path

let base_url = format!(
...

Fixed in 8e1106e. Both edit_wiki_page.rs and create_work_item.rs now percent-encode the path segments (project, wiki_name, work_item_type) using percent_encoding::utf8_percent_encode with a PATH_SEGMENT set that encodes #, ?, /, and space — the structural delimiters that would silently corrupt the URL if left raw. percent-encoding 2.3 was added as an explicit Cargo.toml dependency (it was already a transitive dep via reqwest/url).

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • api.github.com (HTTP Only)
    • Triggering command: /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw proxy --allow api.github.com /lib64/ld-linux-x86-64.so.2 -pie 0e408.00mdgrb20p5x77eazk2p9gjyy.1cyioin.rcgu.o 0e408.01teq1ycpdi29xtq38m58avzw.1cyioin.rcgu.o 0e408.04wdksz2udhbsmhbmz31ifrn2.1cyioin.rcgu.o 0e408.0roi7kz8fyd01vr8wopkslw4t.1cyioin.rcgu.o 0e408.0w0s0sshyajplf2l699oxuwfk.1cyioin.rcgu.o 0e408.0zz0925kng4sqhjswpq47h7d1.1cyioin.rcgu.o 0e408.1h8m7eedzoqh87j6ntnde3cky.1cyioin.rcgu.o 0e408.21isguhevtn32dqcdl1j05fjf.1cyioin.rcgu.o 0e408.27hw7b2y70hemqls64pwyeeau.1cyioin.rcgu.o 0e408.2ap69xa5jhcu8bzvi8nf665ru.1cyioin.rcgu.o 0e408.2l7sln5w36yyxwfvup96uk3iy.1cyioin.rcgu.o 0e408.2z3o4ny3w29nexl27pg3lovk0.1cyioin.rcgu.o 0e408.31ku1szu3n6wt3joczv7xzi8i.1cyioin.rcgu.o 0e408.3q1z69vza816v6i52bhfjdqwn.1cyioin.rcgu.o (packet block)
    • Triggering command: /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw proxy --allow api.github.com /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/proxy_tests-90c56adb783e73e6.1now /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/proxy_tests-90c56adb783e73e6.1-fuse-ld=lld /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/proxy_tests-90c56adb783e73e6.2-z /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/proxy_tests-90c56adb783e73e6.2relro /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/proxy_tests-90c56adb783e73e6.2-o /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/proxy_tests-90c56adb783e73e6.2kxma�� /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/proxy_tests-90c56adb783e73e6.2nkx7ezwyyqca5jhkfvfksmjz.0gf8kx7.rcgu.o /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/proxy_tests-90c56adb783e73e6.2tuk7drm704exbz4hyppemjx0.0gf8kx7.rcgu.o l2k4�� baok3emibk8wmp8dmv4.1mpvzir.rcgu.o lb4en5ayn09l2b6c20h.1mpvzir.rcgu.o f/tempfile-3.24.--crate-type s/tracing_attribcc s/tracing_attrib-m64 s/tracing_attrib/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/rustctIinKE/symbols.o known-linux-gnu//home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/proxy_tests-90c56adb783e73e6.0--eh-frame-hdr (packet block)
    • Triggering command: /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw proxy --allow api.github.com kxma�� nkx7ezwyyqca5jhkfvfksmjz.0gf8kx7.rcgu.o tuk7drm704exbz4hyppemjx0.0gf8kx7.rcgu.o e-486665cf5f9386--emit=dep-info,link e-486665cf5f9386cc e-486665cf5f9386-m64 e-486665cf5f9386/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/rustcblWFcx/symbols.o e-486665cf5f9386/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-5c39ca9a324ebf83.0139go-U0 e-48�� mbols.o c56adb783e73e6.0/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-5c39ca9a324ebf83.03zwhb-plugin c56adb783e73e6.0/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-5c39ca9a324ebf83.04o8qg/usr/libexec/gcc/x86_64-linux-gnu/13/liblto_plugin.so c56adb783e73e6.0git c56adb783e73e6.1show c56adb783e73e6.14ccf0b27b40a2836d4365b2a0238c62f80880939:src/tools/edit_wiki_page.rs c56adb783e73e6.1/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-5c39ca9a324ebf83.0gs97t--eh-frame-hdr (packet block)
  • dev.azure.com
    • Triggering command: /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw proxy --allow api.github.com --allow dev.azure.com --allow *.visualstudio.com 0e408.04wdksz2udhbsmhbmz31ifrn2.1cyioin.rcgu.o 0e408.0roi7kz8fyd01vr8wopkslw4t.1cyioin.rcgu.o 0e408.0w0s0sshyajplf2l699oxuwfk.1cyioin.rcgu.o 0e408.0zz0925kng4sqhjswpq47h7d1.1cyioin.rcgu.o 0e408.1h8m7eedzoqh87j6ntnde3cky.1cyioin.rcgu.o 0e408.21isguhevtn32dqcdl1j05fjf.1cyioin.rcgu.o 0e408.27hw7b2y70hemqls64pwyeeau.1cyioin.rcgu.o 0e408.2ap69xa5jhcu8bzvi8nf665ru.1cyioin.rcgu.o 0e408.2l7sln5w36yyxwfvup96uk3iy.1cyioin.rcgu.o 0e408.2z3o4ny3w29nexl27pg3lovk0.1cyioin.rcgu.o 0e408.31ku1szu3n6wt3joczv7xzi8i.1cyioin.rcgu.o 0e408.3q1z69vza816v6i52bhfjdqwn.1cyioin.rcgu.o (dns block)
    • Triggering command: /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw proxy --allow api.github.com --allow dev.azure.com --allow *.visualstudio.com /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/proxy_tests-90c56adb783e73e6.2/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-5c39ca9a324ebf83 /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/proxy_tests-90c56adb783e73e6.2kxma�� /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/proxy_tests-90c56adb783e73e6.2nkx7ezwyyqca5jhkfvfksmjz.0gf8kx7.rcgu.o /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/proxy_tests-90c56adb783e73e6.2tuk7drm704exbz4hyppemjx0.0gf8kx7.rcgu.o l2k4�� baok3emibk8wmp8dmv4.1mpvzir.rcgu.o lb4en5ayn09l2b6c20h.1mpvzir.rcgu.o mbols.o -3723d82190d9318cc -3723d82190d9318-m64 -3723d82190d9318/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/rustctIinKE/symbols.o -3723d82190d9318/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/proxy_tests-90c56adb783e73e6.0-plugin-opt=-fresolution=/tmp/ccuIoaPb.res (dns block)
    • Triggering command: /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw proxy --allow api.github.com --allow dev.azure.com --allow *.visualstudio.com e-486665cf5f9386cc e-486665cf5f9386-m64 e-486665cf5f9386/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/rustcblWFcx/symbols.o e-486665cf5f9386/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-5c39ca9a324ebf83.0139gosgqilmsx1rcmhyzc662.0mm17mr.rcgu.o e-48�� mbols.o c56adb783e73e6.0/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-5c39ca9a324ebf83.03zwhb-flavor c56adb783e73e6.0/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-5c39ca9a324ebf83.04o8qggnu c56adb783e73e6.0git c56adb783e73e6.1show c56adb783e73e6.14ccf0b27b40a2836d4365b2a0238c62f80880939:src/tools/edit_wiki_page.rs c56adb783e73e6.1/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-5c39ca9a324ebf83.0gs97t-plugin-opt=-fresolution=/tmp/ccWGD8gP.res (dns block)
  • msazuresphere.visualstudio.com
    • Triggering command: /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw proxy --allow api.github.com --allow dev.azure.com --allow *.visualstudio.com 0e408.04wdksz2udhbsmhbmz31ifrn2.1cyioin.rcgu.o 0e408.0roi7kz8fyd01vr8wopkslw4t.1cyioin.rcgu.o 0e408.0w0s0sshyajplf2l699oxuwfk.1cyioin.rcgu.o 0e408.0zz0925kng4sqhjswpq47h7d1.1cyioin.rcgu.o 0e408.1h8m7eedzoqh87j6ntnde3cky.1cyioin.rcgu.o 0e408.21isguhevtn32dqcdl1j05fjf.1cyioin.rcgu.o 0e408.27hw7b2y70hemqls64pwyeeau.1cyioin.rcgu.o 0e408.2ap69xa5jhcu8bzvi8nf665ru.1cyioin.rcgu.o 0e408.2l7sln5w36yyxwfvup96uk3iy.1cyioin.rcgu.o 0e408.2z3o4ny3w29nexl27pg3lovk0.1cyioin.rcgu.o 0e408.31ku1szu3n6wt3joczv7xzi8i.1cyioin.rcgu.o 0e408.3q1z69vza816v6i52bhfjdqwn.1cyioin.rcgu.o (dns block)
    • Triggering command: /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw proxy --allow api.github.com --allow dev.azure.com --allow *.visualstudio.com /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/proxy_tests-90c56adb783e73e6.2/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-5c39ca9a324ebf83 /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/proxy_tests-90c56adb783e73e6.2kxma�� /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/proxy_tests-90c56adb783e73e6.2nkx7ezwyyqca5jhkfvfksmjz.0gf8kx7.rcgu.o /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/proxy_tests-90c56adb783e73e6.2tuk7drm704exbz4hyppemjx0.0gf8kx7.rcgu.o l2k4�� baok3emibk8wmp8dmv4.1mpvzir.rcgu.o lb4en5ayn09l2b6c20h.1mpvzir.rcgu.o mbols.o -3723d82190d9318cc -3723d82190d9318-m64 -3723d82190d9318/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/rustctIinKE/symbols.o -3723d82190d9318/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/proxy_tests-90c56adb783e73e6.0-plugin-opt=-fresolution=/tmp/ccuIoaPb.res (dns block)
    • Triggering command: /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw proxy --allow api.github.com --allow dev.azure.com --allow *.visualstudio.com e-486665cf5f9386cc e-486665cf5f9386-m64 e-486665cf5f9386/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/rustcblWFcx/symbols.o e-486665cf5f9386/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-5c39ca9a324ebf83.0139gosgqilmsx1rcmhyzc662.0mm17mr.rcgu.o e-48�� mbols.o c56adb783e73e6.0/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-5c39ca9a324ebf83.03zwhb-flavor c56adb783e73e6.0/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-5c39ca9a324ebf83.04o8qggnu c56adb783e73e6.0git c56adb783e73e6.1show c56adb783e73e6.14ccf0b27b40a2836d4365b2a0238c62f80880939:src/tools/edit_wiki_page.rs c56adb783e73e6.1/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-5c39ca9a324ebf83.0gs97t-plugin-opt=-fresolution=/tmp/ccWGD8gP.res (dns block)
  • raw.github.com
    • Triggering command: /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw proxy --allow *.github.com /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-5c39ca9a324ebf83.0hucix/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/proxy_tests-90c56adb783e73e6.29zb5tvlqb5tt29okd9ty3n8v.0gf8kx7.rcgu.o /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-5c39ca9a324ebf83.0hwyty/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/proxy_tests-90c56adb783e73e6.2gbp02zi6r6wah1ddwpeqlnpu.0gf8kx7.rcgu.o 0e408.00mdgrb20p5x77eazk2p9gjyy.1cyioin.rcgu.o 0e408.01teq1ycpdi29xtq38m58avzw.1cyioin.rcgu.o 0e408.04wdksz2udhbsmhbmz31ifrn2.1cyioin.rcgu.o 0e408.0roi7kz8fyd01vr8wopkslw4t.1cyioin.rcgu.o 0e408.0w0s0sshyajplf2l699oxuwfk.1cyioin.rcgu.o 0e408.0zz0925kng4sqhjswpq47h7d1.1cyioin.rcgu.o 0e408.1h8m7eedzoqh87j6ntnde3cky.1cyioin.rcgu.o 0e408.21isguhevtn32dqcdl1j05fjf.1cyioin.rcgu.o 0e408.27hw7b2y70hemqls64pwyeeau.1cyioin.rcgu.o 0e408.2ap69xa5jhcu8bzvi8nf665ru.1cyioin.rcgu.o 0e408.2l7sln5w36yyxwfvup96uk3iy.1cyioin.rcgu.o 0e408.2z3o4ny3w29nexl27pg3lovk0.1cyioin.rcgu.o 0e408.31ku1szu3n6wt3joczv7xzi8i.1cyioin.rcgu.o 0e408.3q1z69vza816v6i52bhfjdqwn.1cyioin.rcgu.o (dns block)
    • Triggering command: /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw proxy --allow *.github.com /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/proxy_tests-90c56adb783e73e6.1/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-5c39ca9a324ebf83.0md5qe5dutswaws174h5iuhoq.0mm17mr.rcgu.o /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/proxy_tests-90c56adb783e73e6.1/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-5c39ca9a324ebf83.0mosvevliifzznub1pu1ta9nd.0mm17mr.rcgu.o /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/proxy_tests-90c56adb783e73e6.2/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-5c39ca9a324ebf83.0rdep2l2k4lgotqksrier2b0t.0mm17mr.rcgu.o /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/proxy_tests-90c56adb783e73e6.2/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-5c39ca9a324ebf83.0stugybaok3emibk8wmp8dmv4.0mm17mr.rcgu.o /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/proxy_tests-90c56adb783e73e6.2/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-5c39ca9a324ebf83.0zvminlb4en5ayn09l2b6c20h.0mm17mr.rcgu.o /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/proxy_tests-90c56adb783e73e6.2kxma�� /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/proxy_tests-90c56adb783e73e6.2nkx7ezwyyqca5jhkfvfksmjz.0gf8kx7.rcgu.o /home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/proxy_tests-90c56adb783e73e6.2tuk7drm704exbz4hyppemjx0.0gf8kx7.rcgu.o l2k4�� baok3emibk8wmp8dmv4.1mpvzir.rcgu.o lb4en5ayn09l2b6c20h.1mpvzir.rcgu.o known-linux-gnu/--crate-type s/tracing_attribcc s/tracing_attrib-m64 s/tracing_attrib/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/rustctIinKE/symbols.o 8b16cf8321/out/p/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/proxy_tests-90c56adb783e73e6.0/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-5c39ca9a324ebf83.03zwhbw6du63m9e7k3dgsssj3.0mm17mr.rcgu.o (dns block)
    • Triggering command: /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw /home/REDACTED/work/ado-aw/ado-aw/target/debug/ado-aw proxy --allow *.github.com kxma�� nkx7ezwyyqca5jhkfvfksmjz.0gf8kx7.rcgu.o tuk7drm704exbz4hyppemjx0.0gf8kx7.rcgu.o lib/rustlib/x86_64-REDACTED-linux-gnu/bin/self-contained/cc a869db8d.paste.5cc a869db8d.paste.5-m64 a869db8d.paste.5/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/rustcblWFcx/symbols.o a869db8d.paste.5/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-5c39ca9a324ebf83.0139go-U0 a869�� mbols.o c56adb783e73e6.0/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-5c39ca9a324ebf83.03zwhb-m64 c56adb783e73e6.0/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-5c39ca9a324ebf83.04o8qg/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/rustciBCMk7/symbols.o c56adb783e73e6.0git c56adb783e73e6.1show c56adb783e73e6.14ccf0b27b40a2836d4365b2a0238c62f80880939:src/tools/edit_wiki_page.rs c56adb783e73e6.1/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-5c39ca9a324ebf83.0gs97t/home/REDACTED/work/ado-aw/ado-aw/target/debug/deps/ado_aw-5c39ca9a324ebf83.03zwhbw6du63m9e7k3dgsssj3.1nn9ifj.rcgu.o (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

@jamesadevine
Copy link
Collaborator

/rust-review

@github-actions
Copy link
Contributor

github-actions bot commented Mar 19, 2026

Rust PR Reviewer completed successfully!

@github-actions
Copy link
Contributor

🔍 Rust PR Review

Summary: Solid implementation with good security fundamentals — one weak test and one code-quality issue worth addressing before merge.


Findings

🐛 Bugs / Logic Issues

  • src/tools/edit_wiki_page.rs:725–753test_execute_create_if_missing_false_rejected is effectively a dead test. The test comment admits the intended path (actually exercising the create_if_missing guard in execute_impl) was abandoned in favour of testing config deserialization only. The guard at line 288 (if !page_exists && !config.create_if_missing) is never exercised by the test suite. If this guard regresses, no test catches it. Either mock the HTTP call or restructure execute_impl to expose a testable helper that checks the guard without making a network request.

⚠️ Suggestions

  • src/tools/edit_wiki_page.rs:18 and src/tools/create_work_item.rs:18 — duplicate PATH_SEGMENT constant. Both files define the exact same &AsciiSet. Since it was freshly introduced in create_work_item.rs as part of this PR, this is a good time to lift it to src/tools/mod.rs (or a small src/tools/url.rs utility) so future tools can share it without copying.

  • src/tools/edit_wiki_page.rs:36–52validate() doesn't check for null bytes in path. create_pr.rs (line 1040) and memory.rs (line 53–56) both call ensure!(!path.contains('\0'), ...) explicitly. Null bytes are stripped by sanitize_fields() in both stages so there's no actual exploit path here, but the explicit check keeps validate() consistent with project convention and makes intent clear.


✅ What Looks Good

  • Path-prefix enforcement correctly uses starts_with(&format!("{prefix}/")) rather than a bare starts_with(prefix), preventing /agent-output from matching /agent-outputevil.
  • Belt-and-suspenders .. check: validated in Stage 1 (validate()) and re-checked in Stage 2 (execute_impl), consistent with the rest of the codebase.
  • ETag-based optimistic concurrency: the GET→ETag→PUT flow prevents silent overwrite races on existing pages.
  • edit-wiki-page added to WRITE_REQUIRING_SAFE_OUTPUTS in common.rs — compilation fails without a permissions.write service connection, matching the security model for create-pull-request and create-work-item.
  • URL-encoding of project and wiki_name in the base URL prevents URL structure corruption for values with spaces, #, ?, or /.
  • The silent write pattern (let _ = self.write_safe_output_file(...).await) is consistent with every other MCP tool handler in mcp.rs.

Generated by Rust PR Reviewer for issue #58 ·

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants