Add live support for ContentAnalysis and DataLossPrevention policies
Categories
(Enterprise Products :: Firefox, enhancement)
Tracking
(Not tracked)
People
(Reporter: jmendez, Unassigned, NeedInfo)
References
(Blocks 1 open bug)
Details
Attachments
(2 files)
When implementing this, be sure to update use of setPrefIfPresentAndLock in these policies to be robust to a scenario where a policy property was previously present and then was removed for the same active policy (see PR comment for example/context).
Comment 2•1 month ago
|
||
Comment 3•24 days ago
|
||
Authored by https://github.com/jonathanmendez
https://github.com/mozilla/enterprise-firefox/commit/0adfa3decc38a9500aee4c8498180dbcbed7b69b
[enterprise-main] Bug 2058222 - Add live support for ContentaAnalysis and DataLossPrevention policies
Authored by https://github.com/jonathanmendez
https://github.com/mozilla/enterprise-firefox/commit/f872e93cb147cef6c728ae6d7983a2280590c288
[enterprise-main] Merge pull request #1218 from jonathanmendez/dlp-policy-live
Comment 4•20 days ago
|
||
@jmendez Could you help provide a test plan for anything that QA can test with reasonable efforts? You can take a look at the other bugs that added live support. Each one of them has a test plan comment.
This is a test plan put together by claude. At this point I have only briefly skimmed and edited it. From my initial scan it looks correct, but I will keep the needinfo live here for me to review this more thoroughly.
Test Plan
This bug makes both ContentAnalysis (external agent) and DataLossPrevention (built-in engine) live: they can be added, edited, swapped, and removed without a restart, and the two arbitrate against each other on every update.
Prerequisite note (please read first)
Full rule enforcement by the built-in engine (an actual warn/block dialog quoting the rule's Message) requires the ability to retrieve the DLP module from the console, which as of this writing is not yet implemented. Without it, interception still fires and fails closed, showing Unable to connect to Firefox Enterprise DLP Engine. Paste denied. That message is not a bug -- it is the expected fail-closed path, and it is a good liveness signal: it proves the interception point turned on live in an already-running tab. Every test case below is written to work in that state. FallbackResult: "block" is used throughout because "allow" would let the action through silently with nothing to observe.
Setup
Windows/macOS/Linux desktop, Firefox Enterprise 155+, fresh profile. Probe domains:
chatgpt.com-- matched by the paste ruledropbox.com-- matched by the upload ruleexample.com-- matched by nothing (control)
Before applying any policy, open a second browser window and a tab on https://example.com/, and leave both open for the whole run. The bugs fixed here were only observable when activation happened after the window and the content process already existed -- a window opened after the policy arrives would have masked them.
How to verify the result of each test case
-
about:policies#active-- listsContentAnalysis/DataLossPreventionand their current config. Reload after each change. -
The DLP indicator (shield-ish button in the toolbar/titlebar) -- present only while content analysis (from either policy) is active. Hover for the tooltip:
Data loss prevention (DLP) by <agent name>. Click for more info.Click it for the Data protection panel, which also names the agent. The agent name is how you tell the two providers apart: the built-in engine is alwaysFirefox Enterprise DLP Engine; the external agent uses whateverAgentNamethe policy set. -
about:support> Content Analysis section --Active,Connected to agent,Agent Path,Request Count. Reload the page after each change; it does not update live.Request Countresetting to 0 means the backend was rebuilt; continuing from its previous value means the change was absorbed by the existing backend. -
about:config, filterbrowser.contentanalysis.-- check values, and that policy-set prefs are locked (not editable). After policy removal they must be unlocked and back at their defaults. -
Actual behavior -- in the tab that was already open before the policy arrived, navigate to a probe domain and paste into a text field (or start a file upload / print, per the rule). Expect either the rule's own warn/block dialog (with the WASM provider extension installed) or
Unable to connect to <agent name>.(without it). Onexample.comnothing should happen.
At every step, confirm the change takes effect without restarting the browser, and that it lands in both the original window and the second window.
Test cases
0. Pre-setup baseline
With no policies active, confirm:
- No DLP indicator in either window.
about:support> Content Analysis:Active= false.about:config:browser.contentanalysis.enabled= false, unlocked;browser.contentanalysis.allow_url_regex_list=^about:(?!blank|srcdoc).*(its shipped default -- note this value, case 7 checks it comes back);browser.contentanalysis.dlp_rules= empty.- Paste into a field on
chatgpt.com-- nothing is intercepted.
1. Apply DataLossPrevention (built-in engine on, live)
In the console, set DataLossPrevention:
{
"FallbackResult": "block",
"Rules": [
{
"Name": "warn-ai-paste",
"Enabled": true,
"Actions": ["TextPaste"],
"Domains": ["chatgpt.com"],
"Type": "warn",
"Message": "Pasting work data into AI services may violate company policy."
}
]
}
Expected:
about:policies#activelistsDataLossPreventionwith this config.- The indicator appears in both already-open windows with no restart. Tooltip and panel read
Firefox Enterprise DLP Engine. - Open a third window -- it shows the indicator too.
about:support:Active= true.about:config, all locked:enabled= true,use_wasm_backend= true,agent_name=Firefox Enterprise DLP Engine,agent_timeout= 300,show_blocked_result= true,bypass_for_same_tab_operations= false,deny_url_regex_list= empty,default_result= 0,timeout_result= 0,dlp_rulescontainswarn-ai-paste. Interception points:interception_point.clipboard.enabledandinterception_point.drag_and_drop.enabled= true;download,file_upload,print= false (aTextPasterule enables only the points it needs).- In the tab that was open before the policy arrived, go to
chatgpt.comand paste into a text field -- the paste is intercepted. Paste onexample.com-- unaffected. (This is the content-process check: before this fix an already-running content process kept the stale "inactive" answer and skipped analysis entirely, so please do not open a fresh tab for this step.)
2. Update I -- edit the rules live
{
"FallbackResult": "warn",
"Rules": [
{ "Name": "warn-ai-paste", "Enabled": true, "Actions": ["TextPaste"], "Domains": ["chatgpt.com"], "Type": "warn" },
{ "Name": "block-cloud-upload", "Enabled": true, "Actions": ["FileUpload"], "Domains": ["dropbox.com"], "Type": "block" }
]
}
Expected:
dlp_rulesnow lists both rules;interception_point.file_upload.enabledflips to true,downloadandprintstay false.default_resultandtimeout_resultboth = 1 (warn).about:support:Request Countcontinues from its previous value rather than resetting to 0 -- a rules-only edit must not rebuild the engine.- A file upload on
dropbox.comis now intercepted; the paste rule still works.
3. Update II -- a disabled rule must not leave its hooks running
Set "Enabled": false on block-cloud-upload, leaving everything else the same.
Expected: interception_point.file_upload.enabled returns to false, uploads on dropbox.com are no longer intercepted, and dlp_rules still contains both rules (the engine applies the Enabled flag itself, so seeing both listed is correct).
4. Update III -- external agent takes over live
Add ContentAnalysis without touching DataLossPrevention (this is the diffing case: only the ContentAnalysis callbacks run, but arbitration is still recomputed from the whole active set):
{
"ContentAnalysis": {
"Enabled": true,
"AgentName": "Acme DLP",
"PipePathName": "acme_pipe_a"
},
"DataLossPrevention": {
"FallbackResult": "block",
"Rules": [
{ "Name": "warn-ai-paste", "Enabled": true, "Actions": ["TextPaste"], "Domains": ["chatgpt.com"], "Type": "warn" }
]
}
}
Expected:
use_wasm_backend= false -- the enabled external agent wins over the built-in engine.dlp_rulesis empty: the built-in rules are withdrawn while the agent is authoritative.- Indicator tooltip/panel now read
Acme DLP, in both windows, live. about:support:Agent Pathshows the pipe path,Connected to agent= false (no agent is running),Request Countreset to 0 -- the backend was swapped, not reused.- Paste into a field on any page --
Unable to connect to Acme DLP.(the external agent's default interception points are broader than the built-in engine's, so this is expected onexample.comtoo).
5. Update IV -- external connection change vs. an unrelated change
- Change
PipePathNametoacme_pipe_b(everything else identical). Expected:pipe_path_name=acme_pipe_b, still the external agent, andRequest Countreset to 0 (connection settings are baked in at construction, so this must rebuild). - Now change only
ShowBlockedResulttofalse. Expected:show_blocked_result= false, andRequest Countdoes not reset -- an unrelated change must not churn the agent connection.
6. Update V -- flip Enabled with both policies present
Set ContentAnalysis.Enabled to false, keeping both policies and their other fields.
Expected: a disabled ContentAnalysis block does not suppress the built-in engine, so use_wasm_backend flips back to true, dlp_rules contains warn-ai-paste again, agent_name is back to Firefox Enterprise DLP Engine (check the tooltip), and Request Count resets to 0. Flipping it back to true returns to Acme DLP. Repeat once or twice -- it must survive repeated flips without a restart.
7. Update VI -- no stale configuration across a provider switch
- Set only:
{
"ContentAnalysis": {
"Enabled": true,
"AgentName": "Acme DLP",
"PipePathName": "acme_pipe_b",
"AllowUrlRegexList": "https://allowed\\.example\\.com/.*",
"DenyUrlRegexList": "https://denied\\.example\\.com/.*"
}
}
Confirm allow_url_regex_list and deny_url_regex_list hold those values.
- Now replace the whole set with only the
DataLossPreventionpolicy from case 1.
Expected:
use_wasm_backend= true,dlp_rulespopulated, tooltip =Firefox Enterprise DLP Engine.deny_url_regex_list= empty.allow_url_regex_list=^about:(?!blank|srcdoc).*-- back to its shipped default, not the agent's value and not empty.pipe_path_name,client_signature,max_connections,is_per_userare unlocked and no longer hold the agent's values.
8. Remove
Remove both ContentAnalysis and DataLossPrevention from the policy set.
Expected:
about:policies#activelists neither.- The indicator is gone from every open window, live.
about:support:Active= false.about:config: everybrowser.contentanalysis.*pref is unlocked and back at its default --enabled= false,dlp_rulesempty,agent_name=A DLP agent,allow_url_regex_list=^about:(?!blank|srcdoc).*. (Note: theinterception_point.*.enabledprefs revert to their built-in defaults, most of which aretrue. That is correct -- nothing is intercepted becauseenabledis false.)- In the tab that has been open the whole time, paste on
chatgpt.comand upload ondropbox.com-- neither is intercepted, and no error notification appears.
9. Regression check -- ContentAnalysis present but disabled, alone
Set only:
{ "ContentAnalysis": { "Enabled": false, "AgentName": "Acme DLP" } }
Expected (pre-existing behavior, must be preserved): enabled = false and locked, use_wasm_backend = false and locked, the rest of the block's config locked at the policy's values, no indicator, nothing intercepted. Removing the policy then unlocks everything as in case 8.
Comment 6•17 days ago
|
||
This is a test plan put together by claude. At this point I have only briefly skimmed and edited it. From my initial scan it looks correct, but I will keep the needinfo live here for me to review this more thoroughly.
Thanks @jmendez! Once you think it's good to be tested with, you can flag qe-verify +.
Updated•3 days ago
|
Comment 7•1 day ago
•
|
||
Verified fixed using Firefox Enterprise 155.0 (20260828072535) on Windows 11, MacOS 25 and Ubuntu 24 using the attached DLP add-on and setting up a sample content analysis agent then going through the test-cases from comment 5.
Both ContentAnalysis and DataLossPrevention can be added, edited, removed live without a browser restart.
Updated•1 day ago
|
Description
•