mirror of
https://github.com/tiennm99/ccs.git
synced 2026-07-16 12:15:57 +00:00
fix(kiro): eliminate TOCTOU in token fingerprinting and harden tests
Cache file content in RawTokenCandidate to avoid double-reading token files (TOCTOU race between metadata extraction and fingerprinting). Rename stale test description and add fingerprint fields to test snapshots so they exercise the same comparison path as production.
This commit is contained in:
@@ -62,7 +62,7 @@ type TokenCandidate = {
|
||||
fingerprint: string;
|
||||
};
|
||||
|
||||
type RawTokenCandidate = Omit<TokenCandidate, 'accountId' | 'fingerprint'>;
|
||||
type RawTokenCandidate = Omit<TokenCandidate, 'accountId' | 'fingerprint'> & { content: string };
|
||||
|
||||
function buildTokenFingerprint(content: string): string {
|
||||
return createHash('sha256').update(content).digest('hex');
|
||||
@@ -92,6 +92,7 @@ function listTokenCandidates(provider: CLIProxyProvider, tokenDir: string): Toke
|
||||
{
|
||||
file,
|
||||
filePath,
|
||||
content,
|
||||
email,
|
||||
projectId,
|
||||
mtimeMs: stats.mtimeMs,
|
||||
@@ -122,7 +123,6 @@ function listTokenCandidates(provider: CLIProxyProvider, tokenDir: string): Toke
|
||||
|
||||
return rawCandidates
|
||||
.map((rawCandidate) => {
|
||||
const content = fs.readFileSync(rawCandidate.filePath, 'utf-8');
|
||||
const duplicateEmailCount = rawCandidate.email
|
||||
? (duplicateEmailCounts.get(rawCandidate.email.toLowerCase()) ?? 1)
|
||||
: 1;
|
||||
@@ -138,7 +138,7 @@ function listTokenCandidates(provider: CLIProxyProvider, tokenDir: string): Toke
|
||||
return {
|
||||
...rawCandidate,
|
||||
accountId,
|
||||
fingerprint: buildTokenFingerprint(content),
|
||||
fingerprint: buildTokenFingerprint(rawCandidate.content),
|
||||
};
|
||||
})
|
||||
.sort((left, right) => right.mtimeMs - left.mtimeMs);
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
} from '../../../src/cliproxy/auth/oauth-process';
|
||||
|
||||
describe('oauth-process stderr parsing', () => {
|
||||
it('ignores non-ghcp providers', () => {
|
||||
it('does not match provider-specific patterns for other providers', () => {
|
||||
const stderr =
|
||||
'time="2026-03-03T10:00:00Z" level=error msg="GitHub Copilot authentication failed: example"';
|
||||
|
||||
@@ -55,8 +55,8 @@ describe('oauth-process successful exit analysis', () => {
|
||||
it('treats unchanged existing kiro tokens as a failed add-account attempt', () => {
|
||||
const result = analyzeSuccessfulAuthExit({
|
||||
provider: 'kiro',
|
||||
knownTokenFiles: [{ file: 'kiro-existing.json', mtimeMs: 100 }],
|
||||
currentTokenFiles: [{ file: 'kiro-existing.json', mtimeMs: 100 }],
|
||||
knownTokenFiles: [{ file: 'kiro-existing.json', mtimeMs: 100, fingerprint: 'same' }],
|
||||
currentTokenFiles: [{ file: 'kiro-existing.json', mtimeMs: 100, fingerprint: 'same' }],
|
||||
stdoutData:
|
||||
'[error] Kiro IDC authentication failed: login failed: failed to register client: register client failed (status 400)',
|
||||
stderrData: '',
|
||||
|
||||
Reference in New Issue
Block a user