Summary
microsoft/apm-action's default behavior runs apm install before any audit invocation. When a PR tampers with a deployed managed file (e.g. edits .github/instructions/secure-coding-base.instructions.md to weaken a security rule), apm install re-deploys the upstream version BEFORE the audit runs, silently overwriting the tamper. Audit then sees the pristine file and passes — even though the PR ships malicious content.
Repro
- Repo wires
microsoft/apm-action@v1 with default settings.
- PR edits one line of a deployed instruction file under
.github/instructions/ or .github/hooks/.
- Action runs:
apm install overwrites the tampered file from the upstream plugin source.
apm audit runs against the now-pristine file. PASSES.
- PR merges. Tampered content is in
main's history but not in the deployed tree — until someone runs apm install locally and the PR's edits are silently lost.
Either outcome (merge of bad intent into history; or silent loss of the edit) is broken.
Suggested fix
Two options, both better than today:
A. Add audit-only mode (recommended). Expose an action input that runs the apm CLI install (so audit can use it) but does NOT re-deploy files. Audit sees the as-committed file state, drift / content-integrity catch the tamper.
B. Default behavior change. apm install in CI should be a no-op when apm.lock.yaml is present and the deployed file hashes match what's in the lockfile. Tamper is a hash mismatch; re-deploying silently overwriting it is the bug.
Workaround (proven)
Wire your own reusable workflow that uses microsoft/apm-action with setup-only: true (apm CLI on PATH, no install/deploy), then runs apm audit --ci --no-drift directly. content-integrity check then sees the tamper via lockfile hash drift and fails the gate. Working example: DevExpGbb/zava-agent-config/.github/workflows/apm-audit.yml@v5.1.2.
Why this matters
Drift detection is the WHOLE POINT of deployed_file_hashes in the lockfile (https://microsoft.github.io/apm/guides/drift-detection/). The default action behavior makes that detection structurally impossible in CI. Most consumers will use the action by default and assume it audits what's committed. It does not.
Context
Discovered while building a 5-beat governance demo for an enterprise pilot. Beat 5 specifically demos a malicious instruction-file edit; surfacing it required moving off the action's default invocation.
Summary
microsoft/apm-action's default behavior runsapm installbefore any audit invocation. When a PR tampers with a deployed managed file (e.g. edits.github/instructions/secure-coding-base.instructions.mdto weaken a security rule),apm installre-deploys the upstream version BEFORE the audit runs, silently overwriting the tamper. Audit then sees the pristine file and passes — even though the PR ships malicious content.Repro
microsoft/apm-action@v1with default settings..github/instructions/or.github/hooks/.apm installoverwrites the tampered file from the upstream plugin source.apm auditruns against the now-pristine file. PASSES.main's history but not in the deployed tree — until someone runsapm installlocally and the PR's edits are silently lost.Either outcome (merge of bad intent into history; or silent loss of the edit) is broken.
Suggested fix
Two options, both better than today:
A. Add
audit-onlymode (recommended). Expose an action input that runs the apm CLI install (so audit can use it) but does NOT re-deploy files. Audit sees the as-committed file state, drift / content-integrity catch the tamper.B. Default behavior change.
apm installin CI should be a no-op whenapm.lock.yamlis present and the deployed file hashes match what's in the lockfile. Tamper is a hash mismatch; re-deploying silently overwriting it is the bug.Workaround (proven)
Wire your own reusable workflow that uses
microsoft/apm-actionwithsetup-only: true(apm CLI on PATH, no install/deploy), then runsapm audit --ci --no-driftdirectly.content-integritycheck then sees the tamper via lockfile hash drift and fails the gate. Working example:DevExpGbb/zava-agent-config/.github/workflows/apm-audit.yml@v5.1.2.Why this matters
Drift detection is the WHOLE POINT of
deployed_file_hashesin the lockfile (https://microsoft.github.io/apm/guides/drift-detection/). The default action behavior makes that detection structurally impossible in CI. Most consumers will use the action by default and assume it audits what's committed. It does not.Context
Discovered while building a 5-beat governance demo for an enterprise pilot. Beat 5 specifically demos a malicious instruction-file edit; surfacing it required moving off the action's default invocation.