Nova Act is initialized with secure defaults to protect against unintended file access and malicious actions. You can relax these restrictions based on your use case through SecurityOptions and state guardrails.
Control which local files the browser can navigate to using file:// URLs:
from nova_act import NovaAct, SecurityOptions# Allow specific directorysecurity_options = SecurityOptions( allowed_file_open_paths=["/home/nova-act/shared/*"])with NovaAct( starting_page="file:///home/nova-act/shared/index.html", security_options=security_options) as nova: nova.act("Navigate to the reports page")
Control which local files can be uploaded to websites:
from nova_act import NovaAct, SecurityOptionsupload_filename = "/upload_path/upload_me.pdf"security_options = SecurityOptions( allowed_file_upload_paths=["/upload_path/*"])with NovaAct( starting_page="https://example.com/upload", security_options=security_options) as nova: nova.act(f"upload {upload_filename} using the upload receipt button")
Important security note: Pick allowed_file_upload_paths narrowly to minimize Nova Act’s filesystem access and prevent data exfiltration by malicious websites or content.
State guardrails allow you to control which URLs the agent can visit during execution. They run after each observation and before invoking the next step.
def blocklist_guardrail(state: GuardrailInputState) -> GuardrailDecision: """Block specific domains while allowing all others.""" hostname = urlparse(state.browser_url).hostname if not hostname: return GuardrailDecision.BLOCK # Define blocked domains blocked = [ "*.blocked-domain.com", "*.another-blocked-domain.com", "malicious-site.com" ] if any(fnmatch.fnmatch(hostname, pattern) for pattern in blocked): return GuardrailDecision.BLOCK return GuardrailDecision.PASSwith NovaAct( starting_page="https://example.com", state_guardrail=blocklist_guardrail) as nova: nova.act("Search for information")
When a guardrail blocks execution, Nova Act raises ActStateGuardrailError:
from nova_act import NovaAct, ActStateGuardrailErrortry: with NovaAct( starting_page="https://example.com", state_guardrail=my_guardrail ) as nova: nova.act("Navigate to various pages")except ActStateGuardrailError as e: print(f"Agent attempted to access blocked URL: {e}") # Handle the blocked navigation
Use Playwright APIs to enter sensitive data directly:
from getpass import getpassfrom nova_act import NovaActwith NovaAct(starting_page="https://example.com/login") as nova: # Enter username via prompt (safe) nova.act("enter username 'janedoe' and click on the password field") # Collect password securely and type it via Playwright # This does NOT send the password over the network password = getpass("Enter password: ") nova.page.keyboard.type(password) # Continue with login nova.act("click the sign in button")
import osfrom nova_act import NovaAct# Load from environmentapi_key = os.environ.get("API_KEY")credentials = os.environ.get("CREDENTIALS")with NovaAct(starting_page="https://api.example.com") as nova: # Use credentials without exposing in prompts nova.page.goto(f"https://api.example.com?key={api_key}")
Security considerations:
Passwords typed via Playwright may still appear in screenshots if visible on screen
If you instruct Nova Act to take an action on a screen displaying sensitive information, that information will be included in screenshots
On Linux systems without a system-level keyring (Libsecret, KWallet), Chrome saves passwords in plaintext within the profile directory
Nova Act may encounter commands in third-party website content (user-generated posts, search results, etc.). These “prompt injections” can cause unexpected behavior.
def trusted_only_guardrail(state: GuardrailInputState) -> GuardrailDecision: hostname = urlparse(state.browser_url).hostname trusted_domains = ["example.com", "trusted-site.com"] if hostname in trusted_domains: return GuardrailDecision.PASS return GuardrailDecision.BLOCK
Be Specific in Prompts
Provide clear, explicit instructions:
# Good: Specific and directnova.act("Click the blue 'Submit' button at the bottom of the form")# Bad: Vague, leaves room for interpretationnova.act("Submit the form")
Monitor and Review
Always review agent actions, especially when processing user-contributed content:
# Log all actions for reviewresult = nova.act("Search for products")log_action(result.metadata)
Use Extraction Schemas
When extracting data, use strict schemas to validate output:
from pydantic import BaseModelclass ProductInfo(BaseModel): name: str price: floatresult = nova.act_get( "Get product name and price", schema=ProductInfo.model_json_schema())
# Good: Specific paths onlySecurityOptions( allowed_file_upload_paths=["/uploads/receipts/*"])# Bad: All pathsSecurityOptions( allowed_file_upload_paths=["*"])
Regular Security Audits
Periodically review:
Allowed file paths
Guardrail configurations
Access logs
Workflow prompts
Separate Environments
Use different security configurations for dev/prod:
if ENV == "production": security_options = SecurityOptions( allowed_file_upload_paths=["/prod/uploads/*"] )else: security_options = SecurityOptions( allowed_file_upload_paths=["*"] # More permissive for dev )
Log Security Events
Track when guardrails block actions:
try: nova.act("Navigate somewhere")except ActStateGuardrailError as e: security_logger.warning(f"Blocked: {e}") alert_security_team(e)
import tempfileimport osfrom nova_act import NovaAct, SecurityOptions# Create temporary sandbox directorywith tempfile.TemporaryDirectory() as sandbox_dir: # Only allow access to sandbox security_options = SecurityOptions( allowed_file_upload_paths=[f"{sandbox_dir}/*"], allowed_file_open_paths=[f"{sandbox_dir}/*"] ) # Copy trusted files to sandbox os.system(f"cp /trusted/source/* {sandbox_dir}/") with NovaAct( starting_page="https://example.com", security_options=security_options ) as nova: nova.act(f"Upload the file from {sandbox_dir}/data.csv") # Sandbox is automatically cleaned up after block