test: parity regression guard for alias-branch template delimiter neutralization#31712
Conversation
…tests Co-authored-by: szabta89 <1330202+szabta89@users.noreply.github.com>
… neutralization Co-authored-by: szabta89 <1330202+szabta89@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Adds a regression guard ensuring the sanitizeContent() allowed-aliases branch stays behaviorally identical to sanitizeContentCore() with respect to template-delimiter neutralization, preventing a recurrence of the v0.68.3 parity gap where template syntax could pass through unescaped.
Changes:
- Adds parity tests comparing
sanitizeContent(input, { allowedAliases: [...] })vssanitizeContentCore(input)across five template syntaxes plus a combined case. - Updates two Dependabot workflow lock files to resolve the Docker socket path from
DOCKER_HOSTwhen constructing the MCP gatewaydocker runcommand.
Show a summary per file
| File | Description |
|---|---|
| actions/setup/js/sanitize_content.test.cjs | Adds parity regression tests to ensure alias-branch output matches sanitizeContentCore for template syntax escaping. |
| .github/workflows/dependabot-worker.lock.yml | Updates MCP gateway Docker socket mounting logic to respect DOCKER_HOST when present. |
| .github/workflows/dependabot-campaign.lock.yml | Same Docker socket resolution update as worker workflow lock file. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 3/3 changed files
- Comments generated: 3
| let sanitizeContentCore; | ||
|
|
||
| beforeEach(async () => { | ||
| const coreModule = await import("./sanitize_content_core.cjs"); | ||
| sanitizeContentCore = coreModule.sanitizeContentCore; | ||
| }); |
| case "${DOCKER_HOST:-}" in | ||
| unix://* ) DOCKER_SOCK_PATH="${DOCKER_HOST#unix://}" ;; | ||
| /* ) DOCKER_SOCK_PATH="$DOCKER_HOST" ;; | ||
| * ) DOCKER_SOCK_PATH=/var/run/docker.sock ;; | ||
| esac | ||
| DOCKER_SOCK_GID=$(stat -c '%g' "$DOCKER_SOCK_PATH" 2>/dev/null || echo '0') | ||
| export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v '"${DOCKER_SOCK_PATH}"':/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DOCKER_HOST=unix:///var/run/docker.sock -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -e GITHUB_AW_OTEL_TRACE_ID -e GITHUB_AW_OTEL_PARENT_SPAN_ID -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.3.6' |
| case "${DOCKER_HOST:-}" in | ||
| unix://* ) DOCKER_SOCK_PATH="${DOCKER_HOST#unix://}" ;; | ||
| /* ) DOCKER_SOCK_PATH="$DOCKER_HOST" ;; | ||
| * ) DOCKER_SOCK_PATH=/var/run/docker.sock ;; | ||
| esac | ||
| DOCKER_SOCK_GID=$(stat -c '%g' "$DOCKER_SOCK_PATH" 2>/dev/null || echo '0') | ||
| export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v '"${DOCKER_SOCK_PATH}"':/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DOCKER_HOST=unix:///var/run/docker.sock -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -e GITHUB_AW_OTEL_TRACE_ID -e GITHUB_AW_OTEL_PARENT_SPAN_ID -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.3.6' |
|
@copilot review all comments |
…related lock file changes Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Addressed all three reviewer comments:
2 & 3. Unrelated lock file changes: The Docker socket path changes to |
Bug Fix
What was the bug?
In v0.68.3,
sanitizeContent(text, { allowedAliases: [...] })— the only path taken during normal issue/PR-triggered workflows — never calledneutralizeTemplateDelimiters. Template syntax ({{,${,{%,<%=,{#) passed through verbatim into AI-generated safe-output issue bodies and comments.sanitizeContentCoreapplied the escaping correctly; the alias branch did not.The production fix (importing and calling
neutralizeTemplateDelimitersinsanitize_content.cjs) is already present at HEAD. This PR adds the regression test.How did you fix it?
Adds a parity
describeblock tosanitize_content.test.cjsthat importssanitizeContentCoredirectly and asserts, for each of the five template-syntax patterns plus a combined case, that the alias branch produces bit-for-bit identical output:If the alias branch ever drops
neutralizeTemplateDelimitersagain, its output will contain raw template syntax while the core output will have it escaped — the tests fail immediately, exposing the regression before it ships.Testing
6 new parity tests added; all 400 tests pass.