Skip to main content
OISP Sensor identifies which application generated each AI request, transforming raw “OpenAI traffic” into actionable insights like “Cursor made 47 requests, ChatGPT web made 23.”

Why It Matters

Without app identification:
  • “OpenAI API call detected”
With app identification:
  • “Cursor IDE made a GPT-4 request”
  • “ChatGPT web (Chrome) received a response”
  • “Unknown process making DeepSeek calls”
This context enables:
  • Cost attribution by application
  • Per-app policies (allow Cursor, block others)
  • Shadow AI detection (unknown apps using AI)
  • Browser AI visibility (ChatGPT, Claude.ai)

Three-Tier Model

Apps are classified into tiers based on identification confidence:
TierDescriptionExample
UnknownProcess not matchedpython3 making OpenAI calls
IdentifiedMatched by signatureCursor IDE (bundle ID match)
ProfiledFull behavioral profileCursor with expected API patterns

Native App Identification

How It Works

┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│   Capture   │────►│   Process   │────►│    App      │
│   Event     │     │   Context   │     │   Registry  │
└─────────────┘     └─────────────┘     └──────┬──────┘


                                        ┌─────────────┐
                                        │  App Match  │
                                        │  Result     │
                                        └─────────────┘
  1. Capture event includes process PID
  2. Process context extracted (name, path, bundle ID)
  3. App registry matches against signatures
  4. App context attached to event

Signature Types

macOS

# Example: Cursor IDE
platforms:
  macos:
    bundle_id: "com.todesktop.230313mzl4w4u92"
    team_id: "WDNM93K4GX"
    paths:
      - "/Applications/Cursor.app"
    helper_bundles:
      - "com.todesktop.230313mzl4w4u92.helper"

Windows

platforms:
  windows:
    paths:
      - "C:\\Users\\*\\AppData\\Local\\Programs\\cursor\\Cursor.exe"
    publisher: "Cursor, Inc."
    product_name: "Cursor"

Linux

platforms:
  linux:
    paths:
      - "/opt/cursor/cursor"
      - "/usr/bin/cursor"
    executable_names:
      - "cursor"
    desktop_files:
      - "cursor.desktop"

Built-in App Registry

OISP includes signatures for 50+ common AI-enabled apps:
CategoryApps
IDEsCursor, VS Code, Zed, Windsurf
AI AssistantsClaude Desktop, ChatGPT Desktop
TerminalsWarp, iTerm2 (with AI)
BrowsersChrome, Firefox, Safari, Arc, Brave, Edge
Dev ToolsGitHub Copilot, Codeium, Tabnine

Web App Identification

For browser-based AI (ChatGPT, Claude.ai), OISP extracts HTTP headers:

How It Works

┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│   HTTP      │────►│   Extract   │────►│   Web App   │
│   Request   │     │   Headers   │     │   Match     │
└─────────────┘     └─────────────┘     └─────────────┘

       │ Origin: https://chat.openai.com
       │ Referer: https://chat.openai.com/c/abc

  ┌─────────────┐
  │ Web Context │
  │ chatgpt-web │
  └─────────────┘

Headers Used

HeaderPurposeExample
OriginPrimary web app identifierhttps://chat.openai.com
RefererPage contexthttps://chat.openai.com/c/123
User-AgentBrowser identificationChrome/120.0

Web Apps Detected

Web AppOrigin Pattern
ChatGPTchat.openai.com
Claude.aiclaude.ai
Perplexityperplexity.ai
Notion AInotion.so
Google AI Studioaistudio.google.com
Poepoe.com

Output

{
  "process": {
    "name": "Google Chrome",
    "bundle_id": "com.google.Chrome"
  },
  "app": {
    "id": "chrome",
    "name": "Google Chrome",
    "tier": "identified"
  },
  "web": {
    "origin": "https://chat.openai.com",
    "web_app_id": "chatgpt-web",
    "web_app_name": "ChatGPT",
    "web_app_type": "direct"
  }
}

App Registry

External Registry

OISP loads app profiles from the oisp-app-registry:
oisp-app-registry/
├── apps/
│   ├── cursor.yaml
│   ├── vscode.yaml
│   ├── claude-desktop.yaml
│   └── ...
└── web-apps/
    ├── chatgpt.yaml
    ├── claude-ai.yaml
    └── ...

Profile Format

id: cursor
name: Cursor
category: ide
vendor: Anysphere
description: AI-first code editor

platforms:
  macos:
    bundle_id: "com.todesktop.230313mzl4w4u92"
    team_id: "WDNM93K4GX"
    paths:
      - "/Applications/Cursor.app"
    helper_bundles:
      - "com.todesktop.230313mzl4w4u92.helper"

  windows:
    paths:
      - "C:\\Users\\*\\AppData\\Local\\Programs\\cursor\\Cursor.exe"
    publisher: "Cursor, Inc."

  linux:
    paths:
      - "/opt/cursor/cursor"
    executable_names:
      - "cursor"

traffic_patterns:
  providers:
    - openai
    - anthropic
  direct: true
  backend: false

Custom Apps

Add custom app profiles:
# Create custom registry
mkdir -p ~/.config/oisp-sensor/apps

# Add custom app
cat > ~/.config/oisp-sensor/apps/my-app.yaml << 'EOF'
id: my-internal-tool
name: Internal AI Tool
category: internal

platforms:
  linux:
    paths:
      - "/opt/company/ai-tool"
    executable_names:
      - "ai-tool"
EOF
Configure in config.toml:
[app_registry]
custom_path = "~/.config/oisp-sensor/apps"

Traffic Patterns

Direct Traffic

App connects directly to AI provider:
┌─────────┐         ┌─────────┐
│  Cursor │────────►│ OpenAI  │
└─────────┘         └─────────┘

Backend Traffic

App uses intermediate backend:
┌─────────┐    ┌─────────┐    ┌─────────┐
│  MyApp  │───►│ Backend │───►│ OpenAI  │
└─────────┘    └─────────┘    └─────────┘
Backend traffic is harder to attribute—the sensor sees the backend process, not the originating app.

Event Output

With App Identification

{
  "event_type": "ai.request",
  "process": {
    "pid": 12345,
    "name": "Cursor",
    "exe": "/Applications/Cursor.app/Contents/MacOS/Cursor",
    "bundle_id": "com.todesktop.230313mzl4w4u92"
  },
  "app": {
    "id": "cursor",
    "name": "Cursor",
    "tier": "profiled",
    "category": "ide"
  },
  "data": {
    "provider": { "id": "openai" },
    "model": { "id": "gpt-4o" }
  }
}

Without App Identification

{
  "event_type": "ai.request",
  "process": {
    "pid": 54321,
    "name": "python3",
    "exe": "/usr/bin/python3"
  },
  "app": {
    "id": null,
    "tier": "unknown"
  },
  "data": {
    "provider": { "id": "deepseek" }
  }
}

Policy Integration

Use app identification in policies:
policies:
  # Allow only approved apps
  - id: "approved-apps-only"
    match:
      app:
        tier:
          equals: "unknown"
    action: block
    reason: "Only approved apps can use AI"

  # Different rules per app
  - id: "cursor-gpt4"
    match:
      app:
        id:
          equals: "cursor"
      model:
        family: "gpt-4"
    action: allow

  # Block browser AI for contractors
  - id: "no-web-ai-contractors"
    match:
      web:
        web_app_id:
          in: [chatgpt-web, claude-ai]
      actor:
        group:
          in: [contractors]
    action: block

Troubleshooting

App Not Identified

# Check what the sensor sees
oisp-sensor record --output - | jq '.process'

# Verify app registry loaded
oisp-sensor status --verbose

Adding Missing App

  1. Check process details:
    # macOS
    codesign -dv /Applications/MyApp.app
    
    # Linux
    readelf -d /usr/bin/myapp
    
  2. Create profile and submit PR to oisp-app-registry

Web App Not Detected

Check if browser is identified:
oisp-sensor record --output - | jq 'select(.web != null)'
Verify Origin header is being extracted in debug logs:
RUST_LOG=oisp_decode=debug oisp-sensor record