Skip to content

Commit 86321b6

Browse files
committed
feat(core): ensure combo resolution doesn't go into infinite loop #1416
1 parent a3cf324 commit 86321b6

2 files changed

Lines changed: 45 additions & 12 deletions

File tree

packages/core/src/consumed-thing.ts

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -445,20 +445,29 @@ export default class ConsumedThing extends Thing implements IConsumedThing {
445445
}
446446

447447
getSecuritySchemes(security: Array<string>): Array<SecurityScheme> {
448+
const visited = new Set<string>();
449+
448450
const scs: Array<SecurityScheme> = [];
449-
for (const s of security) {
450-
const ws = this.securityDefinitions[s + ""]; // String vs. string (fix wot-typescript-definitions?)
451-
// also push nosec in case of proxy
452-
if (ws != null) {
453-
if (ws.scheme === "combo") {
454-
const combo = ws as ComboSecurityScheme;
455-
const schemes = this.getSecuritySchemes(combo.allOf as string[]);
456-
scs.push(...schemes);
457-
} else {
458-
scs.push(ws);
451+
const visitSchemes = (security: Array<string>) => {
452+
for (const s of security) {
453+
if (visited.has(s)) {
454+
continue;
455+
}
456+
visited.add(s);
457+
458+
const ws = this.securityDefinitions[s + ""]; // String vs. string (fix wot-typescript-definitions?)
459+
// also push nosec in case of proxy
460+
if (ws != null) {
461+
if (ws.scheme === "combo") {
462+
const combo = ws as ComboSecurityScheme;
463+
visitSchemes(combo.allOf as string[]);
464+
} else {
465+
scs.push(ws);
466+
}
459467
}
460468
}
461-
}
469+
};
470+
visitSchemes(security);
462471
return scs;
463472
}
464473

packages/core/test/ClientTest.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -806,7 +806,7 @@ class WoTClientTest {
806806
expect(WoTClientTest.servient.hasClientFor(tcf2.scheme)).to.be.not.true;
807807
}
808808

809-
@test "ensure combo security "(done: Mocha.Done) {
809+
@test "ensure combo security"(done: Mocha.Done) {
810810
try {
811811
const ct = new ConsumedThing(WoTClientTest.servient);
812812
ct.securityDefinitions = {
@@ -873,4 +873,28 @@ class WoTClientTest {
873873
done(err);
874874
}
875875
}
876+
877+
@test "ensure no infinite loop with recursive combo security"(done: Mocha.Done) {
878+
try {
879+
const ct = new ConsumedThing(WoTClientTest.servient);
880+
ct.securityDefinitions = {
881+
// a badly designed combo that goes into infinite loop
882+
combo_sc: {
883+
scheme: "combo",
884+
allOf: ["combo_sc", "combo_sc"],
885+
},
886+
};
887+
ct.security = "basic";
888+
const pc = new TestProtocolClient();
889+
const form: Form = {
890+
href: "https://example.com/",
891+
security: ["combo_sc"],
892+
};
893+
ct.ensureClientSecurity(pc, form);
894+
expect(pc.securitySchemes.length).equals(0);
895+
done();
896+
} catch (err) {
897+
done(err);
898+
}
899+
}
876900
}

0 commit comments

Comments
 (0)