From b12204c842fd66ef41b8ea27a0162b7a41b9775b Mon Sep 17 00:00:00 2001 From: adpare Date: Thu, 17 Sep 2026 14:26:17 -0400 Subject: [PATCH] fix: restore some stix fields to enable PUT operations --- app/services/meta-classes/base.service.js | 10 ++++++++++ app/tests/api/techniques/techniques.spec.js | 17 +++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/app/services/meta-classes/base.service.js b/app/services/meta-classes/base.service.js index 8ea36891..1fcde17f 100644 --- a/app/services/meta-classes/base.service.js +++ b/app/services/meta-classes/base.service.js @@ -1050,6 +1050,16 @@ class BaseService extends ServiceWithHooks { data.stix.x_mitre_attack_spec_version = document.stix.x_mitre_attack_spec_version; data.stix.revoked = document.stix.revoked ?? false; + // Workspace-only updates may originate from client STIX projections that + // omit persisted revision fields. Restore them before comparing the STIX + // revision for immutability. + if (document.stix.x_mitre_modified_by_ref !== undefined) { + data.stix.x_mitre_modified_by_ref = document.stix.x_mitre_modified_by_ref; + } + if (document.stix.object_marking_refs !== undefined) { + data.stix.object_marking_refs = document.stix.object_marking_refs; + } + // Preserve x_mitre_is_subtechnique — changing subtechnique status requires // the dedicated conversion endpoints, not the generic update path. if (document.stix.x_mitre_is_subtechnique !== undefined) { diff --git a/app/tests/api/techniques/techniques.spec.js b/app/tests/api/techniques/techniques.spec.js index c4908369..e1454ab4 100644 --- a/app/tests/api/techniques/techniques.spec.js +++ b/app/tests/api/techniques/techniques.spec.js @@ -213,6 +213,23 @@ describe('Techniques Basic API', function () { expect(res.body.message).toContain('immutable'); }); + it('PUT /api/techniques accepts a workspace update with omitted persisted STIX fields', async function () { + const body = cloneForCreate(technique1); + delete body.stix.x_mitre_modified_by_ref; + delete body.stix.object_marking_refs; + + const res = await request(app) + .put('/api/techniques/' + technique1.stix.id + '/modified/' + technique1.stix.modified) + .send(body) + .set('Accept', 'application/json') + .set('Cookie', `${passportCookie.name}=${passportCookie.value}`) + .expect(200) + .expect('Content-Type', /json/); + + expect(res.body.stix.x_mitre_modified_by_ref).toBe(technique1.stix.x_mitre_modified_by_ref); + expect(res.body.stix.object_marking_refs).toEqual(technique1.stix.object_marking_refs); + }); + it('POST /api/techniques does not create a technique with the same id and modified date', async function () { const body = cloneForCreate(technique1); await request(app)