skip to content

Permissions & Policy Files

The permission classes and .policy grant syntax that backed SecurityManager, together with protection domains and the stack-intersection rule for effective permissions. Historical, but it explains why the model was so hard to use correctly.

part ofJavaoverview, primer and where to startread it →
on this pageshow

questions

4

What is a Java Permission, and how does a .policy file grant permissions to code?

level: juniorimportance: should knowfreq 30%

answer

  1. Permission = class + target + actions
  2. grant codeBase "url" { permission ...; };
  3. imply(): broader permission covers narrower request
  4. FilePermission / SocketPermission / RuntimePermission
  5. Deprecated for removal — JEP 411

basics

~20 s

A Permission is an object that names one capability the code is allowed to use, like reading a file or opening a network connection. A .policy text file lists grant blocks that hand those capabilities to code from a given location.

solid answer

~40 s

In the legacy Java security model, a Permission is a typed object describing one specific capability: a class (e.g. FilePermission), a target (what it applies to, like a file path), and often an action (read, write). The runtime checks whether the currently running code holds the needed permission before performing a sensitive operation. Permissions are granted declaratively in a .policy file made of grant blocks: `grant codeBase "..." { permission java.io.FilePermission "/tmp/*", "read"; };`. Each grant ties a set of permissions to a code source (a URL and optionally a signer). At startup the JVM loads the policy, builds a Policy object, and uses it to decide what each piece of code may do. This whole mechanism is part of the SecurityManager era and is now deprecated for removal.

code

java · 14 lines
java
// A FilePermission object built in code:
FilePermission p = new FilePermission("/tmp/-", "read,write");

// p.implies(...) answers "does p cover this narrower request?"
boolean ok = p.implies(new FilePermission("/tmp/logs/app.log", "read")); // true

/* Equivalent grant in an app.policy file:

grant codeBase "file:/opt/app/lib/-" {
    permission java.io.FilePermission "/tmp/-", "read,write";
};

Run with:  java -Djava.security.manager -Djava.security.policy=app.policy MyApp
*/

go deeper

for a junior

Can say a Permission represents one allowed capability and a .policy file's grant blocks hand capabilities to code from a location.

for a middle

Knows the class/target/actions structure, the grant codeBase syntax, the common permission classes, and how -Djava.security.policy wires it in.

for a senior

Explains imply() semantics, codeBase vs signedBy vs Principal scoping, append-vs-replace (= vs ==), and that the whole model is deprecated for removal.

for a principal

Frames it historically — why it existed (untrusted-code sandbox), why it failed in practice, JEP 411 removal, and what replaced the concern (OS/container isolation, no in-JVM sandbox).

## The problem this solves Java was designed so you could run code you did not fully trust — classically, applets downloaded from a web page. The question was: how do you let downloaded code do *some* things (draw on screen) but not *others* (read your hard drive)? The answer was a fine-grained, capability-based access-control system. The **SecurityManager** was the gatekeeper that intercepted sensitive operations, and **Permissions** + **policy files** were how you described who is allowed to do what. ## What a Permission is A **Permission** is an ordinary Java object (subclass of `java.security.Permission`) that represents *one specific capability*. It has up to three parts: - **Class** — the *kind* of capability. Examples: `java.io.FilePermission` (filesystem), `java.net.SocketPermission` (network), `java.lang.RuntimePermission` (JVM-level abilities like exiting the VM or creating a classloader). - **Target (name)** — *what* it applies to. For a file permission this is a path like `/tmp/*`; for a socket permission a host:port like `example.com:443`. - **Actions** — *which operations* are allowed, as a comma-separated string. For `FilePermission`: `read`, `write`, `execute`, `delete`. Some permissions (like many `RuntimePermission`s) have no actions — just the name, e.g. `exitVM`. So `new FilePermission("/tmp/*", "read")` means "may read any file directly inside /tmp". Key behavior: permissions know how to **imply** each other. A permission for `/tmp/-` (the whole subtree, recursively) *implies* `/tmp/a.txt`. "read,write" implies "read". When the system checks an access, it asks the granted permissions "does any of you imply the one I need?". ## What a .policy file is A **policy file** is a plain-text file describing which permissions are granted to which code. Its core construct is the **grant block**: ``` grant codeBase "file:/opt/app/lib/-" { permission java.io.FilePermission "/var/data/*", "read,write"; permission java.net.SocketPermission "db.internal:5432", "connect"; }; ``` Reading it: "Code loaded from the URL `file:/opt/app/lib/-` is granted the right to read/write files in /var/data and to open a connection to db.internal:5432." The `codeBase` is a **URL** identifying where the code came from; a trailing `/-` matches that directory and all subdirectories, `/*` matches just the JARs in that directory. You can also restrict by **`signedBy "alias"`** (code signed by a key whose certificate is in the keystore) and **`Principal`** (the authenticated user, used with JAAS). A grant with **no codeBase** applies to *all* code. ## How it is wired up 1. The default policy file ships in the JDK (`$JAVA_HOME/conf/security/java.policy`); you add your own with `-Djava.security.policy=app.policy` (or `==app.policy` to *replace* rather than *append*). 2. The system `Policy` object parses these files into `Permission` objects. 3. You enable enforcement by installing a SecurityManager (historically `-Djava.security.manager`). 4. When sensitive code runs (e.g. `new FileInputStream`), the library calls `SecurityManager.checkPermission(perm)`, which delegates to `AccessController.checkPermission(perm)`, which walks the call stack and asks the Policy whether every frame is allowed. ## Important historical status The **SecurityManager and this entire permission/policy mechanism are deprecated for removal** (JEP 411, Java 17). They are effectively unmaintained and slated to disappear, because the sandbox-untrusted-code use case (applets, Web Start) is dead and the model was hard to use correctly. You should *recognize* it (legacy systems, interview trivia, understanding old stack traces) but not build new systems on it.

  • What does a trailing /- versus /* mean in a FilePermission target?
    /* matches files directly in that directory (one level); /- matches that directory and everything in all subdirectories recursively. The same convention is used for codeBase URLs.
  • How do you point the JVM at your own policy file?
    -Djava.security.policy=app.policy appends it to the default policy; -Djava.security.policy==app.policy (double equals) replaces the default entirely. A SecurityManager must be installed for it to take effect.

saying these in an interview costs you the question

  • Thinking a policy file controls who can log in / authenticate — it controls what code may do, not user accounts.
  • Believing permissions are still actively used in modern apps — the whole model is deprecated for removal.
  • Confusing actions with targets (e.g. saying the path is the action).

context

open as a page

What is a ProtectionDomain, and how do the permissions of code on the call stack get combined during an access check?

level: seniorimportance: should knowfreq 22%

basics

~20 s

A ProtectionDomain groups code from the same source with the permissions granted to it. When code is checked, Java looks at every method on the call stack and only allows the action if every one of them has the permission — the most restrictive caller wins.

open as a page

Why were the SecurityManager, permissions, and policy files deprecated for removal, and what should replace that protection today?

level: principalimportance: should knowfreq 25%

basics

~20 s

The permission/policy sandbox was built to run untrusted in-process code like applets, which no longer exist. It was complex, error-prone, and rarely used correctly, so JEP 411 (Java 17) deprecated it for removal. Today you isolate untrusted code with OS, container, or process boundaries instead.

open as a page

Name the common built-in Permission classes and what each protects. How does AllPermission differ from a specific permission?

level: middleimportance: nice to knowfreq 18%

basics

~20 s

FilePermission guards file access, SocketPermission guards network connections, and RuntimePermission guards JVM abilities like exiting the VM. AllPermission is a wildcard that grants everything at once, so it implies any other permission and should almost never be granted.

open as a page