@@ -22,6 +22,7 @@ interface IntegrityFixture {
2222}
2323
2424const roots : string [ ] = [ ] ;
25+ const MCP_STATE_RECORD = `# nemoclaw-hermes-mcp-state-v1 intended=${ "1" . repeat ( 64 ) } applied=${ "2" . repeat ( 64 ) } ` ;
2526
2627afterEach ( ( ) => {
2728 for ( const root of roots . splice ( 0 ) ) fs . rmSync ( root , { recursive : true , force : true } ) ;
@@ -38,7 +39,18 @@ function writeHash(
3839 envPath : string ,
3940 env : string ,
4041) : void {
41- fs . writeFileSync ( hashPath , `${ digest ( config ) } ${ configPath } \n${ digest ( env ) } ${ envPath } \n` ) ;
42+ fs . writeFileSync (
43+ hashPath ,
44+ `${ digest ( config ) } ${ configPath } \n${ digest ( env ) } ${ envPath } \n${ MCP_STATE_RECORD } \n` ,
45+ ) ;
46+ }
47+
48+ function readHashRecords ( hashPath : string ) : string [ ] {
49+ return fs . readFileSync ( hashPath , "utf-8" ) . split ( "\n" ) . slice ( 0 , - 1 ) ;
50+ }
51+
52+ function writeHashRecords ( hashPath : string , records : readonly string [ ] ) : void {
53+ fs . writeFileSync ( hashPath , `${ records . join ( "\n" ) } \n` ) ;
4254}
4355
4456function createFixture ( ) : IntegrityFixture {
@@ -96,7 +108,7 @@ function runProof(fixture: IntegrityFixture, extraEnv: NodeJS.ProcessEnv = {}) {
96108}
97109
98110describe ( "Hermes managed startup integrity proof" , ( ) => {
99- it ( "accepts a current compatibility hash and one generated API key beyond the strict base" , ( ) => {
111+ it ( "accepts canonical file and MCP state records with one generated API key beyond the strict base (#6427) " , ( ) => {
100112 const fixture = createFixture ( ) ;
101113 const rawStrictCheck = spawnSync ( "sha256sum" , [ "-c" , fixture . strictHashPath , "--status" ] , {
102114 encoding : "utf-8" ,
@@ -111,6 +123,68 @@ describe("Hermes managed startup integrity proof", () => {
111123 expect ( proof . stdout ) . toBe ( "OK\n" ) ;
112124 } ) ;
113125
126+ it ( "rejects a missing Hermes MCP state record (#6427)" , ( ) => {
127+ const fixture = createFixture ( ) ;
128+ const [ configRecord , envRecord ] = readHashRecords ( fixture . compatHashPath ) ;
129+ writeHashRecords ( fixture . compatHashPath , [ configRecord ! , envRecord ! ] ) ;
130+
131+ const proof = runProof ( fixture ) ;
132+ expect ( proof . status ) . not . toBe ( 0 ) ;
133+ expect ( proof . stderr ) . toContain (
134+ "Hermes compatibility hash does not contain exactly three records" ,
135+ ) ;
136+ } ) ;
137+
138+ it ( "rejects a malformed Hermes MCP state record (#6427)" , ( ) => {
139+ const fixture = createFixture ( ) ;
140+ const [ configRecord , envRecord ] = readHashRecords ( fixture . compatHashPath ) ;
141+ writeHashRecords ( fixture . compatHashPath , [
142+ configRecord ! ,
143+ envRecord ! ,
144+ `# nemoclaw-hermes-mcp-state-v1 intended=${ "1" . repeat ( 64 ) } applied=invalid` ,
145+ ] ) ;
146+
147+ const proof = runProof ( fixture ) ;
148+ expect ( proof . status ) . not . toBe ( 0 ) ;
149+ expect ( proof . stderr ) . toContain (
150+ "Hermes compatibility hash contains an unexpected MCP state record" ,
151+ ) ;
152+ } ) ;
153+
154+ it ( "rejects duplicate Hermes MCP state records (#6427)" , ( ) => {
155+ const fixture = createFixture ( ) ;
156+ const records = readHashRecords ( fixture . compatHashPath ) ;
157+ writeHashRecords ( fixture . compatHashPath , [ ...records , MCP_STATE_RECORD ] ) ;
158+
159+ const proof = runProof ( fixture ) ;
160+ expect ( proof . status ) . not . toBe ( 0 ) ;
161+ expect ( proof . stderr ) . toContain (
162+ "Hermes compatibility hash does not contain exactly three records" ,
163+ ) ;
164+ } ) ;
165+
166+ it ( "rejects a reordered Hermes MCP state record (#6427)" , ( ) => {
167+ const fixture = createFixture ( ) ;
168+ const [ configRecord , envRecord , stateRecord ] = readHashRecords ( fixture . compatHashPath ) ;
169+ writeHashRecords ( fixture . compatHashPath , [ stateRecord ! , configRecord ! , envRecord ! ] ) ;
170+
171+ const proof = runProof ( fixture ) ;
172+ expect ( proof . status ) . not . toBe ( 0 ) ;
173+ expect ( proof . stderr ) . toContain ( "Hermes compatibility hash contains an unexpected file record" ) ;
174+ } ) ;
175+
176+ it ( "rejects unexpected records after the Hermes MCP state record (#6427)" , ( ) => {
177+ const fixture = createFixture ( ) ;
178+ const records = readHashRecords ( fixture . compatHashPath ) ;
179+ writeHashRecords ( fixture . compatHashPath , [ ...records , "unexpected" ] ) ;
180+
181+ const proof = runProof ( fixture ) ;
182+ expect ( proof . status ) . not . toBe ( 0 ) ;
183+ expect ( proof . stderr ) . toContain (
184+ "Hermes compatibility hash does not contain exactly three records" ,
185+ ) ;
186+ } ) ;
187+
114188 it ( "rejects non-key environment drift even when the compatibility hash accepts it" , ( ) => {
115189 const fixture = createFixture ( ) ;
116190 const config = fs . readFileSync ( fixture . configPath , "utf-8" ) ;
0 commit comments