What is a Java Permission, and how does a .policy file grant permissions to code?
answer
- Permission = class + target + actions
- grant codeBase "url" { permission ...; };
- imply(): broader permission covers narrower request
- FilePermission / SocketPermission / RuntimePermission
- Deprecated for removal — JEP 411
basics
~20 sA 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 sIn 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// 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
Can say a Permission represents one allowed capability and a .policy file's grant blocks hand capabilities to code from a location.
Knows the class/target/actions structure, the grant codeBase syntax, the common permission classes, and how -Djava.security.policy wires it in.
Explains imply() semantics, codeBase vs signedBy vs Principal scoping, append-vs-replace (= vs ==), and that the whole model is deprecated for removal.
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).