Skip to content

Commit fa871e9

Browse files
committed
fix(loop): allow exact restore Git probes
1 parent 014fc4c commit fa871e9

2 files changed

Lines changed: 52 additions & 1 deletion

File tree

loops/issue-dev-loop/scripts/lib/github-identity.mjs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,21 @@ function authorizedPushBranches(authorization) {
295295

296296
export function assertGitCommandPolicy(role, args, { authorization = null } = {}) {
297297
const subcommand = gitSubcommand(args)
298+
const restoreCleanlinessProbe =
299+
role === 'automation' &&
300+
(sameArguments(args, ['ls-files', '-v', '-z']) ||
301+
sameArguments(args, [
302+
'-c',
303+
'core.fileMode=true',
304+
'diff',
305+
'--quiet',
306+
'--no-ext-diff',
307+
'--no-textconv',
308+
'HEAD',
309+
'--',
310+
]))
311+
if (restoreCleanlinessProbe) return
312+
298313
if (subcommand.name === 'push') {
299314
if (role === 'reviewer') throw new Error('reviewer identity cannot run git push')
300315
const claimBranch = authorization?.issue?.branch

loops/issue-dev-loop/tests/github-identity-routing.test.mjs

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@ import {
3232
canonicalFinalizationRecord,
3333
finalizationRecordDigest,
3434
} from '../scripts/lib/finalization-proof.mjs'
35-
import { resolveExecutable } from '../scripts/lib/github-identity.mjs'
35+
import {
36+
assertGitCommandPolicy,
37+
resolveExecutable,
38+
} from '../scripts/lib/github-identity.mjs'
3639

3740
const execFileAsync = promisify(execFile)
3841
const testDirectory = path.dirname(fileURLToPath(import.meta.url))
@@ -2324,6 +2327,39 @@ test('authenticated remote Git accepts only exact origin and authorized ref shap
23242327
}
23252328
})
23262329

2330+
test('automation allows only the exact restore cleanliness Git probes', () => {
2331+
for (const args of [
2332+
['ls-files', '-v', '-z'],
2333+
[
2334+
'-c',
2335+
'core.fileMode=true',
2336+
'diff',
2337+
'--quiet',
2338+
'--no-ext-diff',
2339+
'--no-textconv',
2340+
'HEAD',
2341+
'--',
2342+
],
2343+
]) {
2344+
assert.doesNotThrow(() => assertGitCommandPolicy('automation', args))
2345+
assert.throws(
2346+
() => assertGitCommandPolicy('reviewer', args),
2347+
/outside the authenticated reviewer command tree/,
2348+
)
2349+
}
2350+
for (const args of [
2351+
['ls-files', '-v'],
2352+
['ls-files', '-v', '-z', '--others'],
2353+
['-c', 'core.fileMode=false', 'diff', '--quiet', 'HEAD', '--'],
2354+
['-c', 'core.fileMode=true', 'diff', 'HEAD', '--'],
2355+
]) {
2356+
assert.throws(
2357+
() => assertGitCommandPolicy('automation', args),
2358+
/outside the authenticated automation command tree/,
2359+
)
2360+
}
2361+
})
2362+
23272363
test('authenticated real Git ignores local execution hooks and configured diff helpers', async () => {
23282364
const fixture = await createFixture({ realGit: true })
23292365
const realGit = await resolveExecutable('git', process.env)

0 commit comments

Comments
 (0)