()
| 221 | // --- Security scenario tests --- |
| 222 | |
| 223 | function testSecurityScenarios() { |
| 224 | console.log("Running security scenario tests..."); |
| 225 | |
| 226 | // Scenario 1: Attacker has resource access in org_attacker, but tries to |
| 227 | // bind target to a site in org_victim. |
| 228 | // verifyResourceAccess passes (sets req.userOrgId = "org_attacker"). |
| 229 | // verifySiteAccess loads site (org_victim), checks site.orgId !== req.userOrgId. |
| 230 | // Expected: 403 Forbidden. |
| 231 | { |
| 232 | const shouldReject = shouldRejectCrossOrgSite( |
| 233 | "org_victim", |
| 234 | "org_attacker" |
| 235 | ); |
| 236 | assertEquals( |
| 237 | shouldReject, |
| 238 | true, |
| 239 | "Scenario 1: Cross-org site binding must be rejected" |
| 240 | ); |
| 241 | } |
| 242 | |
| 243 | // Scenario 2: Attacker has resource access AND site access in another org. |
| 244 | // Even though the user has site access, verifySiteAccess rejects because |
| 245 | // the org-match check runs before the site access check. |
| 246 | // Expected: 403 Forbidden (org mismatch caught before site access check). |
| 247 | { |
| 248 | const shouldReject = shouldRejectCrossOrgSite( |
| 249 | "org_victim", |
| 250 | "org_attacker" |
| 251 | ); |
| 252 | assertEquals( |
| 253 | shouldReject, |
| 254 | true, |
| 255 | "Scenario 2: Cross-org site must be rejected even if user has site access" |
| 256 | ); |
| 257 | } |
| 258 | |
| 259 | // Scenario 3: Legitimate user creates target with site in same org. |
| 260 | // verifyResourceAccess passes, verifySiteAccess org-match passes (same org), |
| 261 | // verifySiteAccess site access passes. |
| 262 | // Expected: 201 Created. |
| 263 | { |
| 264 | const shouldReject = shouldRejectCrossOrgSite( |
| 265 | "org_attacker", |
| 266 | "org_attacker" |
| 267 | ); |
| 268 | assertEquals( |
| 269 | shouldReject, |
| 270 | false, |
| 271 | "Scenario 3: Same-org site must be allowed" |
| 272 | ); |
| 273 | } |
| 274 | |
| 275 | // Scenario 4: WireGuard site in victim org — org mismatch is caught before |
| 276 | // any DB write, pickPort, addPeer, or addTargets side effect. |
| 277 | { |
| 278 | const shouldReject = shouldRejectCrossOrgSite( |
| 279 | "org_victim", |
| 280 | "org_attacker" |
no test coverage detected